package com.bone.util;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
 * String Utility Class This is used to encode passwords programmatically
 * 
 * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
 */
public final class StringUtil {
    private static final Log log = LogFactory.getLog(StringUtil.class);
    private static final String MOBILE_REG = "^(13[0-9]|147|15[0|1|2|3|5|6|7|8|9]|18[8|9|6|3|7|0|2])\\d{8}$";
    private static final String EMAIL_REG = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
    /**
     * Checkstyle rule: utility classes should not have public constructor
     */
    public StringUtil() {
    }
    //~ Methods ================================================================

    public static String realplayMobleAndEmail(final String str){
    	try {
    		String s = str;
        	//手机
        	Pattern p=Pattern.compile(MOBILE_REG);
        	//邮件
        	Pattern p2=Pattern.compile(EMAIL_REG); 
        	Matcher m2=p2.matcher(str); 
        	Matcher m=p.matcher(str); 
        	if(s.length()==11&&m.find()){
        		String st = s.substring(0,7);
        		s =st+"****";
        	}else if (m2.find()) {
        		int i = s.indexOf("@");
        		String st = s.substring(0,i+1);
        		s = st + "****";
    		}
        	return s;
		} catch (Exception e) {
			log.info("匹配手机号码，邮箱号码变为*号error");
			return str;
		}
    }
    public static boolean checkSystem(String userId){
    	if("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".equals(userId)){
    		return false;
    	}
    	return true;
    }
    /**
     * 替换硬回车
     * @param content
     * @return
     */
    public static String replaceBR(String content){
    	return content.replaceAll("\r\n", "<br/>");
    }
	/**
	 * 判断传入的字符串是否为空串,如果是null的就替换为""空字符串.
	 * 
	 * @return
	 */
	public static String replaceNullStr(String str) {
		if(str==null){
			return "";
		}
		if(!isEmptyString(str)){
			if("null".equals(str)){
				str=str.replace("null", "");
				return str;
			}else{
				return str;	
			}
		}else{
			return str;
		}
	}
    /**
     * 替换特殊字符
     */
    public static String realplaySpecialCharacters(String content){
    	String[] strChar = new String[]{"+", "-", "$", "&", "|", "||", "!", "(", ")", "{", "}", "[", "]", "^", "/", "~", "*", "?", ":", "\"", "'",">","<"};
    	for (int i = 0; i < strChar.length; i++) {
			String string = strChar[i];
			content = content.replace(string, "");
		}
    	return content;
    }
    /**
     * Encode a string using algorithm specified in web.xml and return the
     * resulting encrypted password. If exception, the plain credentials
     * string is returned
     *
     * @param password Password or other credentials to use in authenticating
     *        this username
     * @param algorithm Algorithm used to do the digest
     *
     * @return encypted password based on the algorithm.
     */
    public static String encodePassword(String password, String algorithm) {
        byte[] unencodedPassword = password.getBytes();

        MessageDigest md = null;

        try {
            // first create an instance, given the provider
            md = MessageDigest.getInstance(algorithm);
        } catch (Exception e) {
            log.error("Exception: " + e);

            return password;
        }

        md.reset();

        // call the update method one or more times
        // (useful when you don't know the size of your data, eg. stream)
        md.update(unencodedPassword);

        // now calculate the hash
        byte[] encodedPassword = md.digest();

        StringBuffer buf = new StringBuffer();

        for (byte anEncodedPassword : encodedPassword) {
            if ((anEncodedPassword & 0xff) < 0x10) {
                buf.append("0");
            }

            buf.append(Long.toString(anEncodedPassword & 0xff, 16));
        }

        return buf.toString();
    }

    /**
     * Encode a string using Base64 encoding. Used when storing passwords
     * as cookies.
     *
     * This is weak encoding in that anyone can use the decodeString
     * routine to reverse the encoding.
     *
     * @param str the string to encode
     * @return the encoded string
     */
    public static String encodeString(String str)  {
        Base64 encoder = new Base64();
        return String.valueOf(encoder.encode(str.getBytes())).trim();
    }

    /**
     * Decode a string using Base64 encoding.
     *
     * @param str the string to decode
     * @return the decoded string
     */
    public static String decodeString(String str) {
        Base64 dec = new Base64();
        try {
            return String.valueOf(dec.decode(str));
        } catch (Exception de) {
            throw new RuntimeException(de.getMessage(), de.getCause());
        }
    }
    
    public static String nl2br(String showText) {
		return showText == null ? "" : showText.replaceAll("\n", "<BR />");
	}
    
    public static String substr(String str,int len){
    	if (str.length()<len){
    		return str;
    	}
    	return str.substring(0,len)+"...";
    }
    /**
     * Splits a String on a delimiter into a List of Strings.
     * @param str the String to split
     * @param delim the delimiter character(s) to join on (null will split on whitespace)
     * @return a list of Strings
     */
    public static List split(String str, String delim) {
        List splitList = null;
        StringTokenizer st = null;

        if (str == null)
            return splitList;

        if (delim != null)
            st = new StringTokenizer(str, delim);
        else
            st = new StringTokenizer(str);

        if (st != null && st.hasMoreTokens()) {
            splitList = new ArrayList();

            while (st.hasMoreTokens())
                splitList.add(st.nextToken());
        }
        return splitList;
    }
    
    public static boolean included(String ids,String id){
    	StringTokenizer tokens = new StringTokenizer(ids,",");
    	while(tokens.hasMoreTokens()){
    		if (tokens.nextToken().equals("'"+id.trim()+"'")){
    			return true;
    		}
    	}
    	return false;
    }
    
    public static boolean included(String ids,String[] id){
    	for (int i=0;i<id.length;i++){
    		StringTokenizer tokens = new StringTokenizer(ids,",");
	    	while(tokens.hasMoreTokens()){
	    		if (tokens.nextToken().equals("'"+id[i].trim()+"'")){
	    			return true;
	    		}
	    	}
    	}
    	return false;
    }
    /**
     * 根据传入的len长度截断source字符串
     * @param len
     * @param source
     * @return
     */
    public static String cutString(int len,String source){
    	
    	if(source!=null&&source.length()>=len){
    		/*String returnStr = "";
    		String clone = source;
    		while(clone.lastIndexOf("<")>-1&&clone.lastIndexOf("<")>-1){
    			returnStr = clone.substring(beginIndex, endIndex)
    		}*/
    		
    		return source.substring(0, len)+"…";
    	}else{
    		return source;
    	}
    }
    
    public static String cutString2(int len,String source){
    	if(source.length()>=len){
    		return source.substring(0, len)+"… ";
    	}else{
    		return source;
    	}
    }
    
    /**
     * 屏蔽手机的方法
     * @param source 手机号
     * @return
     */
    public static String hiddenMobile(String source) {
    	if (null == source) {
    		return "";
    	}
    	Pattern pattern = Pattern.compile("^1\\d{10}$");

		if (pattern.matcher(source).matches()) {
			return source.substring(0,4) + "****" + source.substring(8);
		} else {
			return source;
		}
    	
    }
    
//    /**
//     * 节目串编方法，传入节目类型和播出时间，获取唯一的码单号<br/>
//     * 被引用处：PromManagerImpl
//     * @param type	节目类型
//     * @param date	播出时间
//     * @param len	播出时长，默认为0000
//     * @return	码单号
//     */
//    public static String getPromUnquieCode(String type,String date,String len){
//    	StringBuffer bf = new StringBuffer("");
//    	StringBuffer buf = new StringBuffer("0000");
//    	UUIDGenerator gen = new UUIDGenerator();
//    	if(date!=null&&!date.trim().equals("")){
//    		date = DateUtil.getDateTime("yyMMdd", date);
//    	}
//    	if(type!=null){
//    		type="a";
//    	}
//    	if(len==null||len.trim().equals("")){
//    		len = "0000";
//    	}else{   		
//    		buf.replace(4 - len.length(), 4, len);
//    	}
//    	
//    	return bf.append(type)
//    				.append(date).append(buf)
//    				.append(gen.generateFor2Pos()).toString();
//    }
   
    /**
     * 生成随机字符串
     * @param random
     * @param len
     * @return
     */
	public String getRandomString( int random, int len ){
	    java.util.Random rd = new java.util.Random();
	    StringBuffer sb = new StringBuffer();
	    int rdGet; // 取得随机数 
	    char ch;
	     
	    for ( int i = 0 ; i < len; i ++ ){
	        rdGet = Math.abs(rd.nextInt()) % 10 + 48 ; // 产生48到57的随机数(0-9的键位值)   
	        //rdGet=Math.abs(rd.nextInt())%26+97; // 产生97到122的随机数(a-z的键位值) 
	        ch = ( char ) rdGet;
	        sb.append( ch );
	    } 	     
	    return sb.toString();
	} 
	/**
	 * 将传入的float保留2位小数
	 * @return
	 */
	public static String formatFloatFor2Pos(Float f){
		java.text.DecimalFormat myformat=new java.text.DecimalFormat("#0.00");		
		return myformat.format(f);   
	}
	/**
	 * 替换null对象或者null字符
	 * @param object
	 * @return
	 * @author dengcheng
	 */
	public static String trimNullValue(String object){
		if(object == null ||"null".equals(object)){
			return ""; 
		}
		return object;
	}
	public static String formatFloatFor2Pos(Float f1,Float f2){
		float ff = f1 - f2;
		java.text.DecimalFormat myformat=new java.text.DecimalFormat("#0.0");		
		return myformat.format(ff);   
	}

	public static String formatFloatFor0Pos(Float f){
		java.text.DecimalFormat myformat=new java.text.DecimalFormat("#0");		
		return myformat.format(f);   
	}
	/**
	 * 过滤html文档
	 * @param inputString
	 * @return
	 */
	public static String filterOutHTMLTags(String inputString) {
		String htmlStr = inputString; // 含html标签的字符串
		String textStr = "";
		java.util.regex.Pattern p_script;
		java.util.regex.Matcher m_script;
		java.util.regex.Pattern p_style;
		java.util.regex.Matcher m_style;
		java.util.regex.Pattern p_html;
		java.util.regex.Matcher m_html;

		try {
			String regEx_script = "<[\\s]*?script[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?script[\\s]*?>"; // 定义script的正则表达式{或<script[^>]*?>[\\s\\S]*?<\\/script>																						// }
			String regEx_style = "<[\\s]*?style[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?style[\\s]*?>"; // 定义style的正则表达式{或<style[^>]*?>[\\s\\S]*?<\\/style>
			String regEx_html = "<[^>]+>"; // 定义HTML标签的正则表达式

			p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
			m_script = p_script.matcher(htmlStr);
			htmlStr = m_script.replaceAll(""); // 过滤script标签

			p_style = Pattern.compile(regEx_style, Pattern.CASE_INSENSITIVE);
			m_style = p_style.matcher(htmlStr);
			htmlStr = m_style.replaceAll(""); // 过滤style标签

			p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
			m_html = p_html.matcher(htmlStr);
			htmlStr = m_html.replaceAll(""); // 过滤html标签

			textStr = htmlStr;
		} catch (Exception e) {
			System.err.println("Html2Text: " + e.getMessage());
		}
		return textStr;// 返回文本字符串
	}
	
	
	/**
	 * 判断传入的字符串是否为空串
	 * @return
	 */
	public static boolean isEmptyString(String str){
		return str==null ? true : str.trim().equals("") ? true : false;
	}
	/**
	 * 根据传入的len值分割str成为一个map，map里的每个元素长度都等于len
	 * @param str
	 * @param len
	 * @return
	 */
	public static Map splitStrByLen(String str,int len){
		Map strMap = new HashMap();
		int cnt = 0;
		if(str!=null){
			if(str.length()>len){
				while(str.length()>len){
					strMap.put(cnt, str.substring(0, len));
					str = str.substring(len,str.length());
					cnt++;
				}
				strMap.put(cnt, str);
			}
			strMap.put(cnt, str);
				
			return strMap;
		}else{
			return null;			
		}
		
	}

	/**
	 * 验证是否是有效的手机号
	 * 
	 * @param mobile 手机号
	 * @return
	 */
	public final static boolean validMobileNumber(final String mobile) {
		if (StringUtils.isEmpty(mobile)) {
			return false;
		}

		Pattern pattern = Pattern.compile(MOBILE_REG);

		if (!pattern.matcher(mobile).matches()) {
			log.info(mobile + "不是有效的手机号码.");
			return false;
		}
		return true;
	}
	
	
	public final static boolean validateUserName(String code){
		Pattern pattern = Pattern.compile("^[A-Za-z0-9]{4,16}+$");
		if (!pattern.matcher(code).matches()) {
			log.info(code + "用户名必须由6-16位数字和字母组成");
			return false;
		}
		return true;
	}
	
	public final static boolean validNickname(final String nickName) {
		/**
		 * @ TODO 配置敏感词
		 */
		return true;
	}
	
	
	/**
	 * 校验是否是有效的邮件地址
	 * 
	 * @param email 邮箱地址
	 * @return
	 */
	public final static boolean validEmail(final String email) {
		if (StringUtils.isEmpty(email)) {
			return false;
		}
		Pattern pattern = Pattern.compile(EMAIL_REG);
		if (!pattern.matcher(email).matches()) {
			log.info(email + "不是有效的邮箱地址.");
			return false;
		}
		return true;
	}
	
	public final static boolean validMembershipCard(final String membershipCard) {
		return true;
	}
	
	public final static String replaceQuoteInJS(final String str) {
		if (null == str) {
			return "";
		} else {
			return str.replaceAll("\\\"", "\\\\\"");
		}
	}
	/**
	 * 替换模板中的变量。变量的标识符为${}。
	 * 例如，模板中${name}变量将会被Map列表中键名为name的键值替换，如果Map列表中不存在所需要
	 * 的键名，则会被替换成空。
	 * @param template 模板
	 * @param data  参数列表
	 * @return 有效的模板内容
	 * @throws Exception Exception
	 */
	public static String composeMessage(final String template, final Map<String, Object> data) throws Exception {
		String regex = "\\$\\{(.+?)\\}";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(template);

		/*
		 * sb用来存储替换过的内容，它会把多次处理过的字符串按源字符串序
		 * 存储起来
		 */
		StringBuffer sb = new StringBuffer();
		while (matcher.find()) {
			String name = matcher.group(1); //键名
			String value = null == data.get(name) ? "" : data.get(name).toString(); //键值
			if (value == null) {
				value = "";
			} else {
				value = value.replaceAll("\\$", "\\\\\\$");
			}

			matcher.appendReplacement(sb, value);
		}

		matcher.appendTail(sb);
		return sb.toString();
	}
	
	/**
	 * 替换或截短用户名
	 * 若用户名是手机号、邮箱或用户名为lv+手机号，则部分字符用*替换，其它根据传入的长度截短
	 * @param len (-1表示不截短)
	 * @param userName
	 * @return
	 */
	public static String replaceOrCutUserName(int len, String userName) {
		Pattern userNamePt = Pattern.compile("^lv[0-9]{11}$");		
        String str = realplayMobleAndEmail(userName);		
        
		if (!str.equals(userName)) {
			return str;
		} else if (userNamePt.matcher(userName).find() && validMobileNumber(userName.substring(2, userName.length()))) {
			return userName.substring(0, userName.length()-4) + "****";
		}
		
		return len == -1 ? str : cutString2(len, str);
	}
	
	public static void main(String[] args) {
//		System.out.println(StringUtil.hiddenMobile("13917677725"));
//		System.out.println(StringUtil.hiddenMobile("53977725"));
//		System.out.println(StringUtil.hiddenMobile("gd"));
		
		System.out.println(StringUtil.replaceOrCutUserName(10, "lv13978"));
		System.out.println(StringUtil.replaceOrCutUserName(10, "13978853652"));
		System.out.println(StringUtil.replaceOrCutUserName(10, "abc@cs.com"));
	}

}
